package ev;

import java.util.*;
import ev.data.*;
import ev.operator.*;

public class HillClimbing implements Assignment1 {

	private int limit = 20000;//terminating condition

	public HillClimbing(){ }

	@Override
	public void emulation() {

			Population initialPopulation;
			ArrayList<Individual> S;
			Individual best=null;
			ArrayList<City> cities;

			//prepare to initial simulation, retrieving required data set
			cities=MyData.getCityData();//get city data from static method
			initialPopulation = new Population(cities);

			int populationsize=100;//set population size in here
			for(int i=0; i<populationsize; i++)
			{
				initialPopulation.add(new Individual(cities.size()));
			}
			//finish retrieving, prepare to start simulation

			S = initialPopulation.getPopulation();
			for(int i=0; i<S.size();i++)
			{
				if(best == null)
				{
					best = S.get(i).copy();
				}else if(S.get(i).getQuality()<best.getQuality())//must use else if
				{
					best = S.get(i).copy();
				}
			}

			System.out.println("Initial result:");
			//System.out.print(best.toString());//print out the initial result
			System.out.println(best.getQuality());//print out the initial result

			while(limit > 0)//algorithm will be terminated when limit reaches
			{
					limit--;

					Random randomGenerator = new Random();
					int index = randomGenerator.nextInt(S.size());
					Individual r = S.get(index).copy();
					r = new Inversion().mutate(r);//mutate
					r.calcualteQuality(cities);//recalculate the mutated quality

					if(r.getQuality()< S.get(index).getQuality())
					{
							S.remove(index);
							S.add(r);

							if(r.getQuality()<best.getQuality())
							{
								best = r.copy();
								/*System.out.println("replace happen, the better result is:");
								System.out.print(r.toString());
					            System.out.println(r.getQuality());*/
							}
					}
			}


			System.out.println("The final result:");
			//System.out.print(best.toString());//print out the final result
			System.out.println(best.getQuality());//print out the final result
	}

}
